Ok(None)
}
+fn find_closest(cmd: &str) -> Option<String> {
+ match list_commands().iter()
+ // doing it this way (instead of just .min_by(|c| c.lev_distance(cmd)))
+ // allows us to only make suggestions that have an edit distance of
+ // 3 or less
+ .map(|c| (c.lev_distance(cmd), c))
+ .filter(|&(d, _): &(uint, &String)| d < 4u)
+ .min_by(|&(d, _)| d) {
+ Some((_, c)) => {
+ Some(c.to_string())
+ },
+ None => None
+ }
+}
+
fn execute_subcommand(cmd: &str, args: &[String], shell: &mut MultiShell) {
let command = match find_command(cmd) {
Some(command) => command,
- None => return handle_error(CliError::new("No such subcommand", 127),
- shell)
+ None => {
+ let msg = match find_closest(cmd) {
+ Some(closest) => format!("No such subcommand\n\n\tDid you mean ``{}''?\n", closest),
+ None => "No such subcommand".to_string()
+ };
+ return handle_error(CliError::new(msg, 127), shell)
+ }
};
let status = Command::new(command)
.args(args)
use cargo::util::process;
use support::paths;
-use support::{project, cargo_dir, mkdir_recursive, ProjectBuilder, ResultTest};
+use support::{execs, project, cargo_dir, mkdir_recursive, ProjectBuilder, ResultTest};
+use hamcrest::{assert_that};
fn setup() {
}
let output = str::from_utf8(output.output.as_slice()).assert();
assert!(output.contains("\n 1\n"), "missing 1: {}", output);
})
+
+test!(find_closest_biuld_to_build {
+ let pr = process(cargo_dir().join("cargo"))
+ .arg("biuld").cwd(paths::root())
+ .env("HOME", Some(paths::home()));
+
+ assert_that(pr,
+ execs().with_status(127)
+ .with_stderr("No such subcommand
+
+Did you mean ``build''?
+
+"));
+})
+
+// if a subcommand is more than 3 edit distance away, we don't make a suggestion
+test!(find_closest_dont_correct_nonsense {
+ let pr = process(cargo_dir().join("cargo"))
+ .arg("asdf").cwd(paths::root())
+ .env("HOME", Some(paths::home()));
+
+ assert_that(pr,
+ execs().with_status(127)
+ .with_stderr("No such subcommand
+"));
+})
+